package com.gylang.sso.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.gylang.common.jwt.JwtUser;
import com.gylang.common.jwt.JwtUtils;
import com.gylang.common.jwt.PayLoad;
import com.gylang.common.jwt.GrantedAuthorityImpl;
import com.gylang.sso.config.RsaKeyProperties;
import com.gylang.sso.utils.HttpUtils;
import lombok.Data;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.util.StringUtils;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author gylang,
 * @data 2019/12/7 12:55,
 * @DESC
 */
@Data
public class JwtVerifyFilter extends BasicAuthenticationFilter {

    private RsaKeyProperties properties;
    private RedisTemplate redisTemplate;
    private String prefix = "user_token:username:";
//    private List<String>

    public JwtVerifyFilter(AuthenticationManager authenticationManager, RsaKeyProperties properties) {
        super(authenticationManager);
        this.properties = properties;
    }

//    @Override
//    protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
//
//        String uri = request.getRequestURI();
//        System.out.println(uri);
//        if ("/sso/login".equals(uri)) {
//
//            return true;
//        } else {
//            return false;
//        }
//    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("doFilterInternal");
        String token = request.getHeader("token");
        if (StringUtils.isEmpty(token)) {   // token不存在

            HttpUtils.returnJson(HttpServletResponse.SC_UNAUTHORIZED, "请先登录", response);
        } else {    //token 存在 从token获取信息
            PayLoad<JwtUser> payLoad = null;
            try {
                payLoad = JwtUtils.getInfoFromToken(token, properties.getPublicKey(), JwtUser.class);
            } catch (Exception e) {
                // token反序列化失败 返回信息
                HttpUtils.returnJson(HttpServletResponse.SC_UNAUTHORIZED, "请先登录", response);
            }

            JwtUser user = (null == payLoad ? null : payLoad.getUserInfo());
            if (null != user) { // 用户信息存在 查询缓存 是否为当前用户

                String redisTokenId = (String) redisTemplate.opsForValue()
                        .get(prefix + payLoad.getUserInfo().getUsername());
                System.out.println("redisTokenId: " + redisTokenId + " == payLoad.getId(): " + payLoad.getId() + " ? " + payLoad.getId().equals(redisTokenId));
                if (payLoad.getId().equals(redisTokenId)) { //redis 缓存token为当前请求用户 账户没过期
                    List<GrantedAuthority> authorities = payLoad.getAuthorities().stream().map(GrantedAuthorityImpl::new).collect(Collectors.toList());
                    System.out.println("authorities" + authorities);
                    UsernamePasswordAuthenticationToken authResult = new UsernamePasswordAuthenticationToken(user.getUsername(), null, authorities);
                    SecurityContextHolder.getContext().setAuthentication(authResult);
                    chain.doFilter(request, response);

                } else {    //redis 查询不到相关记录 账号已过期
                    HttpUtils.returnJson(HttpServletResponse.SC_UNAUTHORIZED, "请先登录", response);

                }
            }

        }

    }


}
